package de.androidbuch.amando.gui;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Spinner;
import de.androidbuch.amando.R;
import de.androidbuch.amando.kontakt.GeoKontakt;
import de.androidbuch.amando.kontakt.GeoKontaktSpeicher;
import de.androidbuch.amando.kontakt.Sortierung;
import de.androidbuch.amando.kontakt.db.GeoKontaktFilterQueryProvider;
import de.androidbuch.amando.kontakt.db.GeoKontaktTbl;


/**
 * Zeigt die Liste der Geokontakte an.
 *  
 * @author Arno Becker, David Müller   2010 visionera gmbh
 * 
 */
public class GeoKontakteAuflistenPerformant 
    extends ListActivity {

  /** Kuerzel fuers Logging. */
  private static final String TAG = 
    GeoKontakteAuflistenPerformant.class.getSimpleName();

  /** Parametername fuer Intent Bundle. */
  static final String IN_PARAM_KONTAKT_ID = "KONTAKT_ID";

  /** Parameter name fuer Intent Bundle. */
  static final String SELECT_KONTAKT = "SELECT_KONTAKT";
  
  /** Filtert den DB Cursor der GeoKontaktliste.   */
  private GeoKontaktFilterQueryProvider mFilterProvider;
  
  /** Rueckgabe aus Kontakt importieren. */
  public static final int ANDROID_KONTAKT_AUSGEWAEHLT = 1;
  
  /** 
   * Spalten des Cursors der Geokontakte, die
   * in der Liste angezeigt werden. 
   */
  private static final String[] ANZEIGE_KONTAKTE = 
    new String[] {
    GeoKontaktTbl.NAME, 
    GeoKontaktTbl.STICHWORT_POS};

  /** IDs im SimpleListView Layout. */
  private static final int[] SIMPLE_LIST_VIEW_IDS = 
    new int[] {
    android.R.id.text1,
    android.R.id.text2 };

  /** 
   * Zeigt an ob die Activity zur Auswahl eines GeoKontakts
   * aufgerufen wurde.
   */
  private boolean mSelectionMode;
  
  /** Schnittstelle zum persistenten Speicher. */
  private GeoKontaktSpeicher mKontaktSpeicher;
  
  @Override
  protected void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    Log.d(TAG, "onCreate(): entered...");
    
    // start tracing to "/sdcard/listview.trace"
    // Debug.startMethodTracing("listview");
    
    setContentView(R.layout.geokontakte_auflisten);    
    
    mSelectionMode = 
      getIntent().getBooleanExtra(SELECT_KONTAKT, false);
    
    if (mSelectionMode) {
      setTitle(R.string
          .txt_geokontakt_auflisten_kontaktauswahl);
    } else {
      setTitle(R.string.txt_geokontakt_auflisten_titel);
    } 
    
    // Allgemeine Form:
    registerForContextMenu(findViewById(android.R.id.list));
    // Abkürzung für ListView:
    //registerForContextMenu(getListView());
    
    ((Spinner) this.findViewById(R.id.sp_sortierung)).
        setOnItemSelectedListener(
            mSpinnerItemAuswahlListener);

    mKontaktSpeicher = new GeoKontaktSpeicher(this);
  }
  
  @Override
  protected void onStart() {
    zeigeGeokontakte();
    super.onStart();    
  }
  
  
  @Override
  protected void onDestroy() {
    // stop tracing
    // Debug.stopMethodTracing();
    mKontaktSpeicher.schliessen();

    super.onDestroy();
  }
  
  /**
   * Zeige die Liste der GeoKontakte an.
   */
  private void zeigeGeokontakte() {
    final long t0 = System.currentTimeMillis();
    final Cursor mcKontakt = mKontaktSpeicher.
      ladeGeoKontaktListe(null);
    Log.i(TAG, "Dauer Anfrage [ms]" +
        (System.currentTimeMillis() - t0));
    startManagingCursor(mcKontakt);

    final PerformanterListenAdapter kontaktAdapter =
        new PerformanterListenAdapter(this,
            android.R.layout.simple_list_item_2, mcKontakt,
            ANZEIGE_KONTAKTE, SIMPLE_LIST_VIEW_IDS);
    
    setListAdapter(kontaktAdapter);
    mFilterProvider = new GeoKontaktFilterQueryProvider(
        mKontaktSpeicher);
    kontaktAdapter.setFilterQueryProvider(mFilterProvider);
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(
        R.menu.geokontakt_auflisten, menu);
    return super.onCreateOptionsMenu(menu);
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
      case R.id.opt_geokontakt_anlegen: 
        final GeoKontakt neuerKontakt = new GeoKontakt();
        // Neuen Kontakt mit Anfangsdaten versehen
        neuerKontakt.startWerteSetzen();
        final Intent i = new Intent(this,
            GeoKontaktBearbeiten.class);    
        startActivity(i);

        return true;
      
      case R.id.opt_geokontakt_importieren: 
        // Android 2.x:  
        final Intent intent = 
            new Intent(Intent.ACTION_PICK, 
            ContactsContract.Contacts.CONTENT_URI);
        
        // Android 1.x:
        // final Intent intent = 
        //    new Intent(Intent.ACTION_PICK, 
        //     People.CONTENT_URI);
        
        startActivityForResult(intent, 
            ANDROID_KONTAKT_AUSGEWAEHLT);        
        return true;
      
      case R.id.opt_hilfe: 
        final Intent j = new Intent(this, 
            HilfeAnzeigen.class);
        startActivity(j);        
        return true;
        
      default: 
        Log.w(TAG, "unbekannte Option gewaehlt: " + item);
    return super.onOptionsItemSelected(item);
  }
  }

  @Override
  protected void onListItemClick(ListView l, View v, 
      int position, long id) {
    super.onListItemClick(l, v, position, id);
    
    if (!mSelectionMode) { // Standardfall: 
      final Intent i = new Intent(this, 
          GeoKontaktAnzeigen.class);
      i.putExtra(GeoKontaktAnzeigen.IN_PARAM_KONTAKT_ID, 
          id);
      Log.d(TAG, "Details anzeigen fuer Kontakt " + id);
      startActivity(i);
    } else {
      final Intent intent = new Intent();
      intent.putExtra(IN_PARAM_KONTAKT_ID, id);
      setResult(Activity.RESULT_OK, intent);
      finish();
    }
  }

  @Override
  public boolean onContextItemSelected(MenuItem item) {
    final AdapterView.AdapterContextMenuInfo info = 
      (AdapterView.AdapterContextMenuInfo) item.
      getMenuInfo();
    if (info.id == AdapterView.INVALID_ROW_ID) {
      Log.d(TAG, "Kein Listeneintrag ausgewählt!");
      return false;
    }
    switch (item.getItemId()) {
      case R.id.opt_geokontakt_details: 
        final Intent i = new Intent(
            this, GeoKontaktAnzeigen.class);
        i.putExtra(GeoKontaktAnzeigen.IN_PARAM_KONTAKT_ID, 
            info.id);
        startActivity(i);
        return true;
      case R.id.opt_geokontakt_bearbeiten: 
        final Intent j = new Intent(this, 
            GeoKontaktBearbeiten.class);
        j.putExtra(GeoKontaktBearbeiten.IN_PARAM_KONTAKT_ID,
            info.id);
        startActivity(j);
        return true;
      
      case R.id.opt_geokontakt_loeschen:         
        mKontaktSpeicher.loescheGeoKontakt(info.id);
        final ListView view = getListView();      
        ((PerformanterListenAdapter) view.getAdapter()).
            getCursor().requery();
        return true;
      
      default: 
        Log.w(TAG, "unbekannte Option gewaehlt: " + item); 
    return super.onContextItemSelected(item);
  }
  }
  
  @Override
  public void onCreateContextMenu(ContextMenu menu, View v,
      ContextMenuInfo menuInfo) {
    
    if (v.getId() == android.R.id.list) {
      getMenuInflater().inflate(
          R.menu.geokontakt_auflisten_kontext, menu);
    }
    super.onCreateContextMenu(menu, v, menuInfo);
  }

  
  
  /**
   * Wenn aufgerufene Intents Daten zurueckgeben landet
   * es hier. 
   * 
   * @param requestCode Vorher übergebener Request-Code
   * @param resultCode In der Sub-Activity gesetzter
   *   Result-Code
   * @param data Von der Sub-Activity übergebene
   *   Ergebnisdaten
   */
  @Override
  protected void onActivityResult(int requestCode, 
      int resultCode, Intent data) {
    Log.d(TAG, "onActivityResult(): entered...");
    if (requestCode == ANDROID_KONTAKT_AUSGEWAEHLT) {
      if (resultCode == RESULT_OK) {  
        importiereAusgewaehltenKontakt(data.getData());
        return;
      }
    }  
    Log.e(TAG, "Kontakt konnte nicht aus den " +
        "Android-Kontakten importiert werden");
  }

  /**
   * Importiert einen im Android Addressbuch ausgewählten
   * Kontakt als neuen Geokontakte.
   * 
   * @param kontaktDaten URI zu ausgewähltem Kontakt
   */
  private void importiereAusgewaehltenKontakt(
      Uri kontaktDaten) {
    final Cursor cursor = managedQuery(kontaktDaten, 
        null, null, null, null);

    if (cursor.moveToFirst()) {  
      // wir haben Kontakt...
      final GeoKontakt geoKontakt = new GeoKontakt();
      // Besser den LOOKUP-KEY verwenden. 
      // Kontaktdatensynchronisation kann die Id 
      // des Kontakts ändern!
      final String lookupKey = cursor.getString(
          cursor.getColumnIndex(
          ContactsContract.Contacts.LOOKUP_KEY)); 
      geoKontakt.lookupKey = lookupKey;
      // DISPLAY_NAME liefert Vor- und Zuname!
      final String displayName = cursor.getString(
          cursor.getColumnIndex(
          ContactsContract.Contacts.DISPLAY_NAME)); 
      geoKontakt.name = displayName; 
      
      // Mobilnummer ermitteln:
      final String hatTelefonNummer = cursor.getString(
          cursor.getColumnIndex(
            ContactsContract.Contacts.HAS_PHONE_NUMBER)); 
      if ("1".equals(hatTelefonNummer)) {   
        final String kontaktId = cursor.getString(
            cursor.getColumnIndex(
              ContactsContract.Contacts._ID)); 
        // Nur die Mobilnummer ermitteln, falls vorhanden:  
        final String whereKlausel = ContactsContract.
          CommonDataKinds.Phone.CONTACT_ID +
            " = " + kontaktId +
            " and " + ContactsContract.CommonDataKinds.
              Phone.TYPE + // Spalte: DATA2
            " = " + ContactsContract.CommonDataKinds.
              Phone.TYPE_MOBILE; // = 2
        final Cursor phones = getContentResolver().query(
            ContactsContract.CommonDataKinds.Phone.
              CONTENT_URI, null, 
            whereKlausel, 
            null, null);       
        // Es könnte auch mehrere Mobilnummern geben, 
        // nehmen wir die erste... 
        if (phones.moveToNext()) {              
          final String mobilNummer = phones.getString(
              phones.getColumnIndex(
                  ContactsContract.CommonDataKinds.
                  Phone.NUMBER));                
          Log.d(TAG, "onActivityResult(): mobilNummer = " + 
              mobilNummer);
          geoKontakt.mobilnummer = mobilNummer;
        } else { // keine Mobilnummer im Kontakt: Warnung
          keineMobilnummerDialog();
          return;
        }
        phones.close(); 
        
        // Neuen Kontakt mit Anfangsdaten versehen
        geoKontakt.startWerteSetzen();
        // Speichere GeoKontakt in DB:
        mKontaktSpeicher.speichereGeoKontakt(geoKontakt);
      }          
    } // end if (cursor.moveToFirst())
    cursor.close();
  }
 
  /**
   * Gibt eine Nachricht aus wenn ein zu importiertender
   * Kontakt keine Mobilfunknummer hat.
   */
  private void keineMobilnummerDialog() {
    final AlertDialog.Builder builder = 
      new AlertDialog.Builder(this);
    builder.setMessage(
        "Auswahl nicht möglich! Dieser Kontakt besitzt " +
          "keine Mobilnummer.")
           .setCancelable(false)
           .setPositiveButton("OK", 
               new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, 
                   int id) {
                 dialog.dismiss();
               }
           });
    builder.create().show();
  }

  /**
   * Ersetzt nach einer Änderung der Sortierung den
   * Cursor, den die Liste als Grundlage verwendet.
   * 
   * @author David Müller, Arno Becker
   */
  private AdapterView.OnItemSelectedListener 
      mSpinnerItemAuswahlListener = 
        new AdapterView.OnItemSelectedListener() {
 
    public void onItemSelected(AdapterView<?> arg0,
        View arg1, int position, long id) {
 
      Cursor sortedCursor;
      switch (position) {
        case 0:
          sortedCursor = mKontaktSpeicher.
            ladeGeoKontaktListe(Sortierung.STANDARD, null);
          break;
        case 1:
          sortedCursor = mKontaktSpeicher.
            ladeGeoKontaktListe(Sortierung.NAME, null);
          break;        
        default:
          sortedCursor = mKontaktSpeicher.
            ladeGeoKontaktListe(null);
      }
      
      final ListView view = getListView();           
      final PerformanterListenAdapter cursorAdapter = 
        ((PerformanterListenAdapter) view.getAdapter());
      
      cursorAdapter.changeCursor(sortedCursor);
    }

    public void onNothingSelected(AdapterView<?> arg0) {
      
    }

  };

  
}
